# TODO: Add comment
# 
# Author: rogb
###############################################################################

setClass("LiborRate",
		representation=list(
				Term="numeric",
				Frequency="character",
				Rate="numeric"
		),contains=c("SituationDate","EffectiveDate","MaturityDate","BasicInstrument","Exchange","DayCountConvention","Price")
)

LiborRate <- function(Term,Frequency,Rate,Currency,Name,SituationDate,DayCountConvention,Exchange){

	EffectiveDate <- getTradingDay(SituationDate + 2,Exchange=Exchange,Direction=1)
	if(Currency=="EUR"){
		EffectiveDate <- plusTradingDay(SituationDate,2,Exchange=Exchange)
	}
	if(Currency=="GBP"){
		EffectiveDate <- SituationDate
	}
	if(Frequency=="ON"){
		EffectiveDate <- SituationDate
		MaturityDate <- getTradingDay(EffectiveDate + Term,Exchange=Exchange,Direction=1,keepMonth = FALSE)
	}
	if(Frequency=="SN"){
		EffectiveDate <- plusTradingDay(SituationDate,2,Exchange=Exchange)
		MaturityDate <- getTradingDay(EffectiveDate + Term,Exchange=Exchange,Direction=1,keepMonth = FALSE)
	}
	if(Frequency=="M"){
		MaturityDate <- plusMonth(EffectiveDate,Term,keepEndOfMonth=TRUE)
		MaturityDate <- getTradingDay(MaturityDate,Exchange=Exchange,Direction=1)
	}
	if(Frequency=="W"){
		MaturityDate <- getTradingDay(SituationDate + Term * 7,Exchange=Exchange,Direction=1,keepMonth = FALSE)
	}
	if(Frequency=="Y"){
		MaturityDate <- plusYear(EffectiveDate,Term,keepEndOfMonth=TRUE)
		MaturityDate <- getTradingDay(MaturityDate,Exchange=Exchange,Direction=1)
	}
	
	
	new("LiborRate",Term=Term,Frequency=Frequency,Rate=Rate,Currency=Currency,Name=Name,SituationDate=SituationDate,EffectiveDate=EffectiveDate,MaturityDate=MaturityDate,DayCountConvention=DayCountConvention,Exchange=Exchange)
}

# L1 <- LiborRate(1,"M",2.34,"CHF","CHF Libor 1M",Sys.Date(),"30/360","SWISSEXCHANGE")
# generateCashFlows(L1)

setMethod("show","LiborRate",function(object){
			cat(object@Currency," Libor Rate as of ",as.character(object@SituationDate),"\n",sep="")
			cat("Term: ",object@Term," ",object@Frequency,"\n",sep="")
			cat("Rate: ",object@Rate,"\n",sep="")
		})

setMethod("generateCashFlows","LiborRate",function(object){
			CF <- 100 + accruedInterest(object@Rate,object@DayCountConvention,1,object@EffectiveDate,object@MaturityDate,object@MaturityDate) 
			CashFlow(object@Currency,object@Name,c(object@EffectiveDate,object@MaturityDate),c(-100,CF))
		})
	
setMethod("presentValue",signature=c("LiborRate","DiscountFactor"),function(object,arg1){
			presentValue(generateCashFlows(object),arg1)
		})

setMethod("presentValue",signature=c("LiborRate","ZeroRateCurve"),function(object,arg1){
			DF <- as.DiscountFactor(arg1)
			presentValue(generateCashFlows(object),DF)
		})

setMethod("estimateIRR",signature=c("LiborRate"),function(object){
			PV <- price(object)
			CF <- generateCashFlows(object)
			n <- dim(CF)[1]
			MaturityDate <- getDate(CF)[n]
			Currency <- currency(object)
			SituationDate <- situationDate(object)
			Date <- getDate(CF)
			f <- function(Rate){
				ZR <- ZeroRateCurve(SituationDate,Currency,object@Name,c(SituationDate,Date),rep(Rate,n+1))
				PV - presentValue(object,ZR)
			}
			Rate <- uniroot(f,c(0,100))$root
			#ZeroRateCurve(SituationDate,Currency,object@Name,c(SituationDate,Date),rep(Rate,n+1))
			Rate
		})

estimateLiborRate <- function(Term,Frequency,Currency,Name,SituationDate,DayCountConvention,Exchange,DF){
	f <- function(Rate){
		# Rate <- 3
		0 - presentValue(LiborRate(Term,Frequency,Rate,Currency,Name,SituationDate,DayCountConvention,Exchange),DF)
	}
	Rate <- uniroot(f,c(0,100))$root
	LiborRate(Term,Frequency,Rate,Currency,Name,SituationDate,DayCountConvention,Exchange)
}

# Term <- 1
# Frequency <- "M"
# Currency <- "CHF"
# Name <- "Libor Rate"
# SituationDate <- Sys.Date()
# DayCountConvention <- "30/360"
# Exchange <- "SWISSEXCHANGE"
# DF <- as(ZR,"DiscountFactor")
# estimateLiborRate(Term,Frequency,Currency,Name,SituationDate,DayCountConvention,Exchange,DF)
